#ifndef RISCV_H
#define RISCV_H

#include <stdint.h>

/* Sv39 常量 */
#define PGSIZE      4096UL
#define PGSHIFT     12
#define PGMASK      (PGSIZE - 1)

/* VPN 提取（level: 2/1/0） */
#define VPN_SHIFT(level)   (12 + 9 * (level))//某级VPN的起始位
#define VPN_MASK(va, lvl)  (((uint64_t)(va) >> VPN_SHIFT(lvl)) & 0x1FF)//提取某级VPN

/* 向下/向上页对齐 */
#define PGROUNDDOWN(a) ((uint64_t)(a) & ~(PGSIZE - 1))
#define PGROUNDUP(sz)  (((uint64_t)(sz) + PGSIZE - 1) & ~(PGSIZE - 1))

/* PTE 位 */
typedef uint64_t pte_t;
typedef uint64_t* pagetable_t;

#define PTE_V (1L << 0)
#define PTE_R (1L << 1)
#define PTE_W (1L << 2)
#define PTE_X (1L << 3)
#define PTE_U (1L << 4)
#define PTE_G (1L << 5)
#define PTE_A (1L << 6)
#define PTE_D (1L << 7)

/* PPN/PTE 与 物理地址换算 */
#define PTE_PPN_SHIFT 10
#define PTE2PA(pte)    (((pte) >> PTE_PPN_SHIFT) << PGSHIFT)
#define PA2PTE(pa)     (((uint64_t)(pa) >> PGSHIFT) << PTE_PPN_SHIFT)

/* SATP：MODE=8 (Sv39) | ASID | PPN */
#define SATP_MODE_SV39 (8UL << 60)
static inline uint64_t MAKE_SATP(pagetable_t pt) {
    uint64_t ppn = ((uint64_t)pt) >> PGSHIFT;
    return SATP_MODE_SV39 | ppn;
}

/* CSR helpers */
static inline void sfence_vma(void) { asm volatile("sfence.vma zero, zero"); }//TLB刷新
static inline void w_satp(uint64_t x) { asm volatile("csrw satp, %0" : : "r"(x)); }
static inline uint64_t r_satp(void) { uint64_t x; asm volatile("csrr %0, satp" : "=r"(x)); return x; }

/* 设备/内存范围 */
#define KERNBASE   0x80000000UL
#define PHYSTOP    0x88000000UL   /* 128MiB 物理上界 */
#define UART0      0x10000000UL

#endif